/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-基础组件封装层-SpringBoot组件封装-缺省实现
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.boot.web.exception.error;

import com.taipingframework.utility.exception.SystemInterrupterException;
import com.taipingframework.utility.constant.ApplicationConstant;
import com.taipingframework.boot.web.response.result.ApiResult;
import com.taipingframework.boot.web.response.status.ApiStatusEnum;
import com.taipingframework.utility.constant.SystemConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashMap;

/**
 * 自定义微服务工程默认的异常处理
 * <p>
 * 重写默认的异常处理机制，不使用SpringBoot自带的`Whitelabel Error Page`，所有后端工程全部默认返回格式统一的json报文。
 */
@Slf4j
@Controller
@RequestMapping("")
public class SpringWebMvcErrorHandler implements ErrorController {

    /**
     * 捕获异常并保存日志记录
     */
    @ResponseBody
    @GetMapping(value = ApplicationConstant.ERROR_PATH, produces = {MediaType.APPLICATION_JSON_VALUE})
    public ApiResult<Serializable> error(HttpServletRequest request) {
        HashMap<String, Object> map = new HashMap<>();
        Enumeration<String> attributes = request.getAttributeNames();
        while (attributes.hasMoreElements()) {
            String name = attributes.nextElement();
            if (name.startsWith(SystemConstant.CHAR_PREFIX_JAVA)) {
                Object value = request.getAttribute(name);
                map.put(name, value);
            }
        }

        ApiResult<Serializable> result = ApiResult.build()
                .setStatus(ApiStatusEnum.ERR_B0001)
                .setResult(map);
        log.error(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), new SystemInterrupterException(ApiStatusEnum.ERR_B0001));
        return result;
    }

    /**
     * 返回系统异常转发的路径
     */
    @Override
    public String getErrorPath() {
        return ApplicationConstant.ERROR_PATH;
    }
}
